/*
 * 大衍之数五十
 * 其用四十有九
 * 分而为二以象两
 * 挂一以象三
 * 揲之以四以象四时
 * 归奇于扐
 * -- 《易经·系辞传》
 */

const { warn, info, log, LogLevel } = require("./log_tool");

const DiagramMap = {
    63: {
        name: "乾",
        statement: {
            gua: "乾，元、亨、利、贞。",
            tuan: "大哉乾元，万物资始，乃统天。云行雨施，品物流行。大明终始，六位时成，时乘六龙以御天。乾道变化，各正性命，保合太和，乃利贞。首出庶物，万国咸宁。",
            xiang: "天行健，君子以自强不息",
            yao: [
                "初九，潜龙勿用。",
                "九二，见龙在田，利见大人。",
                "九三，君子终日乾乾，夕惕若，厉无咎。",
                "九四，或跃在渊，无咎。",
                "九五，飞龙在天，利见大人",
                "上九，亢龙有悔。",
            ],
        },
        order: 1,
    },
    0: {
        name: "坤",
        statement: {
            gua: "坤，元、亨，利牝马之贞。君子有攸往，先迷后得，主利。西南得朋，东北丧朋。安贞，吉。",
            tuan: "至哉坤元！万物资生，乃顺承天。坤厚载物，德合无疆。含弘光大，品物咸亨。牝马地类，行地无疆，柔顺利贞，君子攸行。先迷失道，后顺得常。西南得朋，乃与类行，东北散朋，乃终有庆。安贞之吉，应地无疆。",
            xiang: "地势坤，君子以厚德载物。",
            yao: [
                "初六，履霜，坚冰至。",
                "六二，直、方、大，不习无不利。",
                "六三，含章可贞，或从王事，无成有终。",
                "六四，括囊，无咎无誉。",
                "六五，黄裳，元吉。",
                "上六，龙战于野，其血玄黄。",
            ],
            xiang2: [
                "履霜坚冰，阴始凝也。驯致其道，至坚冰也。",
                "六二之动，直以方也，不习无不利，地道光也。",
                "含章可贞，以时发也，或从王事，知光大也。",
                "括囊无咎，慎不害也。",
                "黄裳元吉，文在中也。",
                "龙战于野，其道穷也。",
            ],
        },
        order: 2,
    },
    34: {
        name: "屯",
        statement: {
            gua: "屯，元、亨、利、贞。勿用有攸往，利建侯。",
            tuan: "屯，刚柔始交而难生。动乎险中，大亨贞。雷雨之动满盈。天造草昧，宜建侯而不宁。",
            xiang: "云雷，屯。君子以经纶",
            yao: [
                "初九，磐桓，利居贞，利建侯。",
                "六二，屯如邅如，乘马班如，匪寇婚媾，女子贞不字，十年乃字。",
                "六三，即鹿无虞，惟入于林中，君子几，不如舍，往吝。",
                "六四，乘马班如，求婚媾；往吉，无不利。",
                "九五，屯其膏。小，贞吉；大，贞凶。",
                "上六，乘马班如，泣血涟如。",
            ],
            xiang2: [
                "虽盘桓，志行正也，以贵下贱，大得民也。",
                "六二之难，乘刚也；十年乃字，反常也。",
                "即鹿无虞，以从禽也；君子舍子，往吝穷也。",
                "求而往，明也。",
                "屯其膏，施未光也。",
                "泣血涟如，何可长也。",
            ],
        },
        order: 3,
    },
    17: {
        name: "蒙",
        order: 4,
    },
    58: {
        name: "需",
        order: 5,
    },
    23: {
        name: "讼",
        order: 6,
    },
    16: {
        name: "师",
        order: 7,
    },
    2: {
        name: "比",
        order: 8,
    },

    59: {
        name: "小畜",
        order: 9,
    },
    55: {
        name: "履",
        order: 10,
    },
    56: {
        name: "泰",
        order: 11,
    },
    7: {
        name: "否",
        order: 12,
    },
    47: {
        name: "同人",
        order: 13,
    },
    61: {
        name: "大有",
        order: 14,
    },
    8: {
        name: "谦",
        order: 15,
    },
    4: {
        name: "豫",
        order: 16,
    },

    38: {
        name: "随",
        order: 17,
    },
    25: {
        name: "蛊",
        order: 18,
    },
    48: {
        name: "临",
        order: 19,
    },
    3: {
        name: "观",
        order: 20,
    },
    37: {
        name: "噬嗑",
        order: 21,
    },
    41: {
        name: "贲",
        gua: "贲，亨，小利，有攸往。",
        tuan: "贲，亨，柔来而文刚，故亨；分刚上而文柔，故小利有攸往，天文也；文明以止，人文也。观乎天文，以察时变；观乎人文，以化成天下。",
        xiang: "山下有火，贲。君子以明庶政，无敢折狱。",
        yao: [
            "初九，贲其趾，舍车而徒。",
            "六二，贲其须。",
            "九三，贲如，濡如，永贞吉。",
            "六四，贲如，皤如，白马翰如；匪寇，婚媾。",
            "六五，贲于丘园，束帛戋戋；吝，终吉。",
            "上九，白贲，无咎。",
        ],
        xiang2: [
            "舍车而徒，义弗乘也。",
            "贲其须，与上兴也。",
            "永贞之吉，终莫之陵也。",
            "六四当位，疑也；非寇婚媾，终无尤也。",
            "六五之吉，有喜也。",
            "白贲，无咎，上得志也。",
        ],
        order: 22,
    },
    1: {
        name: "剥",
        order: 23,
    },
    32: {
        name: "复",
        order: 24,
    },

    39: {
        name: "无妄",
        order: 25,
    },
    57: {
        name: "大畜",
        order: 26,
    },
    33: {
        name: "颐",
        order: 27,
    },
    30: {
        name: "大过",
        order: 28,
    },
    18: {
        name: "坎",
        order: 29,
    },
    45: {
        name: "离",
        order: 30,
    },
    14: {
        name: "咸",
        order: 31,
    },
    28: {
        name: "恒",
        order: 32,
    },

    15: {
        name: "遁",
        order: 33,
    },
    60: {
        name: "大壮",
        order: 34,
    },
    5: {
        name: "晋",
        order: 35,
    },
    40: {
        name: "明夷",
        order: 36,
    },
    43: {
        name: "家人",
        order: 37,
    },
    53: {
        name: "睽",
        statement: {
            gua: "睽，小事吉。",
            xu: "家道穷必乖，故受之以睽。",
            tuan: "睽，火动而上，泽动而下，二女同居，其志不同行。说而丽乎明，柔进而上行，得中而应乎刚，是以小事吉。天地睽而其事同也，男女睽而其志通也，万物睽而其事类也，睽之时用大矣哉！",
            xiang: "上火下泽，睽，君子以同而异。",
            yao: [
                "初九，悔亡，丧马勿逐自复，见恶人无咎。",
                "九二，遇主于巷，无咎。",
                "六三，见舆曳，其牛掣，其人天且劓，无初有终。",
                "九四，睽孤，遇元夫；交孚，厉无咎。",
                "六五，悔亡，厥（jue2）宗噬肤，往何咎。",
                "上九，睽孤，见豕（shi3）负涂，载鬼一车，先张之弧，后说之弧，匪寇婚媾，往遇雨则吉。",
            ],
            xiang2: [
                "见恶人，以避咎也。",
                "遇主于巷，未失道也。",
                "见舆曳，位不当也。无初有终，遇刚也。",
                "交孚无咎，志行也。",
                "厥宗噬肤，往有庆也。",
                "遇雨之吉，群疑亡也。",
            ],
        },
        order: 38,
    },
    10: {
        name: "蹇",
        order: 39,
    },
    20: {
        name: "解",
        order: 40,
    },

    49: {
        name: "损",
        order: 41,
    },
    35: {
        name: "益",
        order: 42,
    },
    62: {
        name: "夬",
        statement: {
            gua: "夬，扬于王庭，孚号有厉，告自邑，不利即戎，利有攸往。",
            xu: "益而不已必决。",
            tuan: "夬，决也，刚决柔也，健而说，决而和。扬于王庭，柔乘五刚也。孚号有厉，其危乃光也。告自邑，不利即戎，所尚乃穷也。利有攸往，刚长乃终也。",
            xiang: "泽上于天，夬，君子以施禄及下，居德则忌。",
            yao: [
                "初九，壮于前趾，往不胜为咎。",
                "九二，惕号，莫夜有戎，勿恤。",
                "九三，壮于頄(qiu2)，有凶，君子夬夬，独行遇雨，若濡有愠，无咎。",
                "九四，臀无肤，其行次且，牵羊悔亡，闻言不信。",
                "九五，苋陆夬夬，中行无咎。",
                "上六，无号，终有凶。",
            ],
            xiang2: [
                "不胜而往，咎也。",
                "有戎勿恤，得中道也。",
                "君子夬夬，终无咎也。",
                "其行次且，位不当也。闻言不信，聪不明也。",
                "中行无咎，中未光也。",
                "无号之凶，终不可长也。",
            ],
            month: "三月",
        },
        order: 43,
    },
    31: {
        name: "姤",
        order: 44,
    },
    6: {
        name: "萃",
        order: 45,
    },
    24: {
        name: "升",
        statement: {
            gua: "升，元亨，用见大人，勿恤，南征吉。",
            xu: "萃者，聚也；聚而上者谓之升，故受之以升。",
            tuan: "柔以时升，巽而顺，刚中而应，是以大亨。用见大人，勿恤，有庆也。南征吉，志行也。",
            xiang: "地中生木，升，君子以慎德，积小以高大。",
            yao: [
                "初六，允升，大吉。",
                "九二，孚乃利用禴(yue4)，无咎。",
                "九三，升虚邑。",
                "六四，王用享于岐山，吉，无咎。",
                "六五，贞吉，升阶。",
                "上六，冥升利于不息之贞。",
            ],
            xiang2: [
                "允升大吉，上合志也。",
                "九二之孚，有喜也。",
                "升虚邑，无所疑也。",
                "王用享于岐山，顺事也。",
                "贞吉升阶，大得志也。",
                "冥升在上，消不富也。",
            ],
        },
        order: 46,
    },
    22: {
        name: "困",
        order: 47,
    },
    26: {
        name: "井",
        order: 48,
    },

    46: {
        name: "革",
        order: 49,
    },
    29: {
        name: "鼎",
        order: 50,
    },
    36: {
        name: "震",
        order: 51,
    },
    9: {
        name: "艮",
        order: 52,
    },
    11: {
        name: "渐",
        order: 53,
    },
    52: {
        name: "归妹",
        order: 54,
    },
    44: {
        name: "丰",
        order: 55,
    },
    13: {
        name: "旅",
        order: 56,
    },

    27: {
        name: "巽",
        order: 57,
    },
    54: {
        name: "兑",
        statement: {
            gua: "兑，亨，利贞。",
            xu: "入而后说之，故受之以兑。",
            tuan: "兑，说也；刚中而柔外，说以利贞，是以顺乎天而应乎人，说以先民，民忘其劳。说以犯难，民忘其死，说之大，民劝矣哉。",
            xiang: "丽泽，兑，君子以朋友讲习。",
            yao: [
                "初九，和兑，吉。",
                "九二，孚兑，吉，悔亡。",
                "六三，来兑，凶。",
                "九四，商兑未宁，介疾有喜。",
                "九五，孚于剥，有厉。",
                "上六，引兑。",
            ],
            xiang2: [
                "和兑之吉，行未疑也。",
                "孚兑之吉，信志也。",
                "来兑之凶，位不当也。",
                "九四之喜，有庆也。",
                "孚于剥，位正当也。",
                "上六引兑，未光也。",
            ],
        },
        order: 58,
    },
    19: {
        name: "涣",
        order: 59,
    },
    50: {
        name: "节",
        order: 60,
    },
    51: {
        name: "中孚",
        order: 61,
    },
    12: {
        name: "小过",
        order: 62,
    },
    42: {
        name: "既济",
        order: 63,
    },
    21: {
        name: "未济",
        order: 64,
    },
};

/*
 * 五十为鼎卦，四十九为革卦
 * 五十为鼎卦，四十九为革卦
 */
const SIX_DIAGRAMS = 6;
const FOUR_SEASONS = 4;
const REPEAT_TIMES = 3;

/**
 * 分而为二以象两
 * @param {*} numTrigram
 * @returns
 */
function divideTrigrams(numTrigram) {
    const idx = 1 + Math.floor(Math.random() * (numTrigram - 1));
    return [idx, numTrigram - idx];
}

/**
 * 揲之以四以象四时, 归奇于扐
 * @param {*} num
 * @returns
 */
function getReminder(num) {
    let reminder = num % FOUR_SEASONS;
    if (reminder === 0) {
        reminder = FOUR_SEASONS;
    }
    return [reminder, num - reminder];
}

function getDiagramValue(num) {
    return num / FOUR_SEASONS;
}

/**
 *
 * @param {number[]} vals
 * @returns
 */
function getDiagramDataByArray(vals) {
    let index = 0;
    const _graphic = "";
    log("\n");
    for (let i = 0, len = vals.length; i < len; i++) {
        const mod = vals[i] % 2;
        const rev_mod = vals[len - 1 - i] % 2;
        log(
            rev_mod ? "======" : "==  ==",
            undefined,
            rev_mod ? LogLevel.ERROR : LogLevel.WHISPER,
            true,
            false,
        );
        index = (index << 1) + mod;
    }
    return DiagramMap[index];
}

function generateDiagramArray() {
    const taichi = 1;
    let tian, di;
    let _tian_reminder, _di_reminder;

    const diagrams = [];

    for (let diagramIndex = 0; diagramIndex < SIX_DIAGRAMS; diagramIndex++) {
        // 大衍之数五十
        let numTokens = 50;
        // 其用四十有九
        numTokens -= taichi;
        for (let repeatIndex = 0; repeatIndex < REPEAT_TIMES; repeatIndex++) {
            // 分而为二以象两
            [tian, di] = divideTrigrams(numTokens);
            // 挂一以象三
            tian -= 1;
            // 揲之以四以象四时, 归奇于扐
            [_tian_reminder, tian] = getReminder(tian);
            [_di_reminder, di] = getReminder(di);
            // console.log(taichi + earth_reminder + sky_reminder);
            numTokens = tian + di;
        }
        const diagram = getDiagramValue(numTokens);
        diagrams.push(diagram);
    }
    return diagrams;
}

function generateAndParseDiagram(raw) {
    const arr = raw || generateDiagramArray();
    return {
        raw: arr,
        diagram: getDiagramDataByArray(arr),
    };
}

function searchDiagram(name) {
    for (const k in DiagramMap) {
        const detail = DiagramMap[k];
        if (detail.name === name) {
            log("\n");
            const num = +k;
            for (let i = 0; i < SIX_DIAGRAMS; ++i) {
                const rev_mod = num & (1 << i);
                log(
                    rev_mod ? "======" : "==  ==",
                    undefined,
                    rev_mod ? LogLevel.ERROR : LogLevel.WHISPER,
                    true,
                    false,
                );
            }
            return detail;
        }
    }
}

module.exports = {
    getDiagramDataByArray,
    generateDiagramArray,
    generateAndParseDiagram,
    searchDiagram,
};
